#include "stdafx.h"
#include "torrent/Bdecoder.hpp"

#include <set>
#include <boost/scoped_ptr.hpp>
#include <boost/filesystem/operations.hpp>

#include "bencode/bencode.h"
#include "torrent/MetaInfo.hpp"
#include "torrent/bencode_helper.hpp"
#include "torrent/utility.hpp"

#if defined(_WIN32) && defined(_DEBUG)
#define new MYDEBUG_NEW
#endif

namespace torrent {

using std::string;

Bdecoder::Bdecoder()
: _node(NULL)
{
}

Bdecoder::~Bdecoder()
{
	clearNode();
}

void Bdecoder::clearNode()
{
	if (_node)
	{
		be_free(_node);
		_node = NULL;
	}
}

MetaInfo Bdecoder::read(const std::string& filename, const std::string& logname)
{
	namespace fs = boost::filesystem;

	unsigned int fileSize = static_cast<unsigned int>(fs::file_size(filename));
	boost::scoped_ptr<char> buf(new char[fileSize]);
	std::ifstream ifs(filename.c_str(), std::ios::in | std::ios::binary);
	ifs.read(buf.get(), fileSize);

	if (!ifs)
		throw std::runtime_error("file io fail");

	clearNode();
	_node = be_decoden(buf.get(), fileSize);

	if ( _node == NULL )
		throw std::runtime_error("decode fail");
	
	freopen(logname.c_str(), "wb", stdout);
	be_dump(_node);
	freopen("CON", "w", stdout);

	MetaInfo ret = bencode_helper::get_meta_info(_node);

	ret._bencodedInfo = bencode_helper::get_bencoded_str_from_node(bencode_helper::get_node_from_key(_node, "info"));

	utility::SHA1Hash hash;
	hash.hashData(ret._bencodedInfo.c_str(), ret._bencodedInfo.length());

	ret._infoHash = hash.hashValue();

	std::set<bencode_helper::StringList> duplicateChecker;
	for (bencode_helper::StringListList::const_iterator i = ret._announceList.begin(); i != ret._announceList.end(); )
	{
		if (duplicateChecker.insert(*i).second == false)
			i = ret._announceList.erase(i);
		else
			++i;
	}

	return ret;
}

void Bdecoder::dump()
{
	be_dump(_node);
}

// namepsace
} 
